﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

namespace DataCoreTechnologies.SqlServer
{
    public sealed partial class Server
    {
        private XmlTextWriter xml = null;
        public void SaveToXml(string fileName)
        {
            xml = new XmlTextWriter(fileName, System.Text.Encoding.Default);

            xml.WriteStartDocument();
            XmlEol();

            WriteServerXml();

            xml.WriteEndDocument();
            xml.Close();
        }
        public void LoadFromXml(string fileName)
        {

        }
        
        //Helper methods
        private void WriteServerXml()
        {
            xml.WriteStartElement("server");
            xml.WriteAttributeString("instanceId", InstanceId.ToString());
            //xml.WriteAttributeString("location", Location);
            xml.WriteAttributeString("name", Name);
            xml.WriteAttributeString("version", Version);
            XmlEol();

            foreach (Database database in _databases)
            {
                if (database.IsInformationLoaded == true) WriteDatabaseXml(database);
            }
            xml.WriteEndElement();
        }
        private void WriteDatabaseXml(Database db)
        {
            xml.WriteStartElement("database");
            
            xml.WriteAttributeString("instanceId", db.InstanceId.ToString());
            xml.WriteAttributeString("name", db.Name);
            xml.WriteAttributeString("sourceDatabaseId", db.SourceDatabaseId.ToString());
            xml.WriteAttributeString("owner", db.Owner);
            xml.WriteAttributeString("createDate", db.CreateDate.ToString());
            xml.WriteAttributeString("compatibilityLevel", db.CompatibilityLevel.ToString());
            xml.WriteAttributeString("collationName", db.CollationName.ToString());
            xml.WriteAttributeString("userAccess", db.UserAccess.ToString());
            xml.WriteAttributeString("userAccessDescription", db.UserAccessDescription);
            xml.WriteAttributeString("isReadOnly", db.IsReadOnly.ToString());
            xml.WriteAttributeString("isAutoCloseOn", db.IsAutoCloseOn.ToString());
            xml.WriteAttributeString("isAutoShrinkOn", db.IsAutoShrinkOn.ToString());
            xml.WriteAttributeString("state", db.State.ToString());
            xml.WriteAttributeString("stateDescription", db.StateDescription);
            xml.WriteAttributeString("isInStandby", db.IsInStandby.ToString());
            xml.WriteAttributeString("isCleanlyShutdown", db.IsCleanlyShutdown.ToString());
            xml.WriteAttributeString("isSupplementalLoggingEnabled", db.IsSupplementalLoggingEnabled.ToString());
            xml.WriteAttributeString("snapshotIsolationState", db.SnapshotIsolationState.ToString());
            xml.WriteAttributeString("snapshotIsolationStateDescription", db.SnapshotIsolationStateDescription);
            xml.WriteAttributeString("isReadCommitedSnapshotOn", db.IsReadCommittedSnapshotOn.ToString());
            xml.WriteAttributeString("recoveryModel", db.RecoveryModel.ToString());
            xml.WriteAttributeString("recoveryModelDescription", db.RecoveryModelDescription);
            xml.WriteAttributeString("pageVerifyOption", db.PageVerifyOption.ToString());
            xml.WriteAttributeString("pageVerifyOptionDescription", db.PageVerifyOptionDescription);

            xml.WriteAttributeString("isAutoCreateStatsOn", db.IsAutoCreateStatsOn.ToString());
            xml.WriteAttributeString("isAutoUpdateStatsOn", db.IsAutoUpdateStatsOn.ToString());
            xml.WriteAttributeString("isAutoUpdateStatsAsyncOn", db.IsAutoUpdateStatsAsyncOn.ToString());
            xml.WriteAttributeString("isAnsiNullDefaultOn", db.IsAnsiNullDefaultOn.ToString());
            xml.WriteAttributeString("isAnsiNullsOn", db.IsAnsiNullsOn.ToString());
            xml.WriteAttributeString("isAnsiPadding", db.IsAnsiPaddingOn.ToString());
            xml.WriteAttributeString("isAnsiWarningsOn", db.IsAnsiWarningsOn.ToString());
            xml.WriteAttributeString("isArithAbortOn", db.IsArithAbortOn.ToString());
            xml.WriteAttributeString("isConcatNullYieldsNullOn", db.IsConcatNullYieldsNullOn.ToString());
            xml.WriteAttributeString("isNumericRoundAbortOn", db.IsNumericRoundAbortOn.ToString());
            xml.WriteAttributeString("isQuotedIdentifierOn", db.IsQuotedIdentifierOn.ToString());
            xml.WriteAttributeString("isRecursiveTriggersOn", db.IsRecursiveTriggersOn.ToString());
            xml.WriteAttributeString("isCursorCloseOnCommitOn", db.IsCursorCloseOnCommitOn.ToString());
            xml.WriteAttributeString("isLocalCursorDefaultOn", db.IsLocalCursorDefault.ToString());
            xml.WriteAttributeString("isFullTextEnabled", db.IsFullTextEnabled.ToString());
            xml.WriteAttributeString("isTrustWorthyOn", db.IsTrustWorthyOn.ToString());
            xml.WriteAttributeString("isDBChainingOn", db.IsDBChainingOn.ToString());
            xml.WriteAttributeString("isParameterizationForced", db.IsParameterizationForced.ToString());
            xml.WriteAttributeString("isMasterKeyEncryptedByServer", db.IsMasterKeyEncryptedByServer.ToString());
            xml.WriteAttributeString("isPublished", db.IsPublished.ToString());
            xml.WriteAttributeString("isSubscribed", db.IsSubscribed.ToString());
            xml.WriteAttributeString("isMergePublished", db.IsMergePublished.ToString());
            xml.WriteAttributeString("isDistributor", db.IsDistributor.ToString());
            xml.WriteAttributeString("isSyncWithBackup", db.IsSyncWithBackup.ToString());

            xml.WriteAttributeString("serviceBrokerGuid", db.ServiceBrokerGuid.ToString());
            xml.WriteAttributeString("isBrokerEnabled", db.IsBrokerEnabled.ToString());
            xml.WriteAttributeString("logReuseWait", db.LogReuseWait.ToString());
            xml.WriteAttributeString("logReuseWaitDescription", db.LogReuseWaitDescription.ToString());
            xml.WriteAttributeString("isDateCorrelationOn", db.IsDateCorrelationOn.ToString());

            xml.WriteAttributeString("dataSpaceUsed", db.DataSpaceUsed.ToString());
            xml.WriteAttributeString("indexSpaceUsed", db.IndexSpaceUsed.ToString());
            xml.WriteAttributeString("dataSpaceAvailable", db.DataSpaceAvailable.ToString());
            xml.WriteAttributeString("description", db.Description);

            xml.WriteAttributeString("id", db.Id.ToString());
            XmlEol();

            WriteSystemTypes(db);
            WriteSchemas(db);

            xml.WriteEndElement();
            XmlEol();
        }
        private void WriteSystemTypes(Database db)
        {
            xml.WriteStartElement("System Types");
            XmlEol();
            foreach (SystemType systemType in db.SystemTypes)
            {
                xml.WriteStartElement("System Type");
                
                xml.WriteAttributeString("name", systemType.Name);
                xml.WriteAttributeString("instanceId", systemType.InstanceId.ToString());
                xml.WriteAttributeString("category", systemType.Category.ToString());
                xml.WriteAttributeString("maxLength", systemType.MaxLength.ToString());
                xml.WriteAttributeString("precision", systemType.Precision.ToString());
                xml.WriteAttributeString("scale", systemType.Scale.ToString());
                xml.WriteAttributeString("collationName", systemType.CollationName);
                xml.WriteAttributeString("isNullable", systemType.IsNullable.ToString());
                xml.WriteAttributeString("id", systemType.Id.ToString());

                xml.WriteEndElement();
                XmlEol();
            }
            xml.WriteEndElement();
            XmlEol();
        }
        private void WriteSchemas(Database db)
        {
            xml.WriteStartElement("Schemas");
            XmlEol();
            
            foreach (Schema schema in db.Schemas)
            {
                xml.WriteStartElement("Schema");

                xml.WriteAttributeString("instanceId", schema.InstanceId.ToString());
                xml.WriteAttributeString("name", schema.Name);
                if (schema.Owner == null)
                    xml.WriteAttributeString("owner", schema.InstanceId.ToString());
                else
                    xml.WriteAttributeString("owner", schema.Owner.InstanceId.ToString());
                xml.WriteAttributeString("id", schema.Id.ToString());

                XmlEol();
                WriteUserTypes(schema);
                WriteTables(schema);
                WriteViews(schema);

                xml.WriteEndElement();
                XmlEol();
            }
            xml.WriteEndElement();
            XmlEol();
        }
        private void WriteUserTypes(Schema schema)
        {
            if (schema.UserTypes.Count() > 0)
            {
                xml.WriteStartElement("User Types");
                XmlEol();

                foreach (UserType userType in schema.UserTypes)
                {
                    xml.WriteStartElement("User Type");

                    xml.WriteAttributeString("instanceId", userType.InstanceId.ToString());
                    xml.WriteAttributeString("name", userType.Name);
                    xml.WriteAttributeString("maxLength", userType.MaxLength.ToString());
                    xml.WriteAttributeString("precision", userType.Precision.ToString());
                    xml.WriteAttributeString("scale", userType.Scale.ToString());
                    xml.WriteAttributeString("collationName", userType.CollationName);
                    xml.WriteAttributeString("isNullable", userType.IsNullable.ToString());
                    xml.WriteAttributeString("systemType", userType.SystemType.InstanceId.ToString());
                    xml.WriteAttributeString("id", userType.Id.ToString());

                    xml.WriteEndElement();
                    XmlEol();
                }

                xml.WriteEndElement();
                XmlEol();
            }
        }
        private void WriteTables(Schema schema)
        {
            if (schema.Tables.Count() > 0)
            {
                xml.WriteStartElement("Tables");
                XmlEol();

                foreach (Table table in schema.Tables)
                {
                    xml.WriteStartElement("Table");

                    xml.WriteAttributeString("instanceId", table.InstanceId.ToString());
                    xml.WriteAttributeString("name", table.Name);
                    xml.WriteAttributeString("createDate", table.CreateDate.ToString());
                    xml.WriteAttributeString("databaseObjectType", table.Type.ToString());
                    xml.WriteAttributeString("id", table.Id.ToString());
                    xml.WriteAttributeString("rowCount", table.RowCount.ToString());
                    xml.WriteAttributeString("dataSpaceUsed", table.DataSpaceUsed.ToString());
                    xml.WriteAttributeString("indexSpaceUsed", table.IndexSpaceUsed.ToString());
                    xml.WriteAttributeString("dataSpaceAvailable", table.DataSpaceAvailable.ToString());

                    if (table.PrimaryKey != null)
                    {
                        XmlEol();
                        WritePrimaryKey(table);
                    } 

                    xml.WriteEndElement();
                    XmlEol();
                }

                xml.WriteEndElement();
                XmlEol();
            }
        }
        private void WritePrimaryKey(Table table)
        {
            xml.WriteStartElement("Primary Key");

            xml.WriteAttributeString("instanceId", table.PrimaryKey.InstanceId.ToString());
            xml.WriteAttributeString("name", table.PrimaryKey.Name);
            //ToDo  add the index reference to each primary key
            xml.WriteAttributeString("index", "");
            xml.WriteAttributeString("createDate", table.PrimaryKey.CreateDate.ToString());
            xml.WriteAttributeString("modifyDate", table.PrimaryKey.ModifyDate.ToString());
            xml.WriteAttributeString("isMicrosoftShipped", table.PrimaryKey.IsMicrosoftShipped.ToString());
            xml.WriteAttributeString("id", table.PrimaryKey.Id.ToString());

            xml.WriteEndElement();
            XmlEol();
        }
        private void WriteViews(Schema schema)
        {

        }
        private void XmlEol()
        {
            xml.WriteWhitespace("\r\n");
        }
    }
}
